﻿using System.Collections.Generic;

namespace Raven
{
    public abstract class GoalComposite<entity_type> : Goal<entity_type>
    {
        protected LinkedList<Goal<entity_type>> _subGoalList;

        public GoalComposite(entity_type owner, GoalType type) : base(owner, type)
        {
            _subGoalList = new LinkedList<Goal<entity_type>>();
        }

        //processes any subgoals that may be present
        protected GoalStatus ProcessSubgoals()
        {
            while (_subGoalList.Count > 0 && (_subGoalList.First.Value.isComplete() || _subGoalList.First.Value.hasFailed()))
            {
                _subGoalList.First.Value.Terminate();
                _subGoalList.RemoveFirst();
            }

            //if any subgoals remain, process the one at the front of the list
            if (_subGoalList.Count > 0)
            { 
                //grab the status of the front-most subgoal
                GoalStatus StatusOfSubGoals = _subGoalList.First.Value.Process();

                //we have to test for the special case where the front-most subgoal
                //reports 'completed' *and* the subgoal list contains additional goals.When
                //this is the case, to ensure the parent keeps processing its subgoal list
                //we must return the 'active' status.
                if (StatusOfSubGoals == GoalStatus.completed && _subGoalList.Count > 1)
                {
                    return GoalStatus.active;
                }

                return StatusOfSubGoals;
            }
  
            //no more subgoals to process - return 'completed'
            return GoalStatus.completed;
        }

        //passes the message to the front-most subgoal
        protected bool ForwardMessageToFrontMostSubgoal(Telegram msg)
        {
            if (_subGoalList.Count > 0)
            {
                return _subGoalList.First.Value.HandleMessage(msg);
            }

            //return false if the message has not been handled
            return false;
        }

        //if a child class of Goal_Composite does not define a message handler
        //the default behavior is to forward the message to the front-most
        //subgoal
        public override bool HandleMessage(Telegram msg)
        {
            return ForwardMessageToFrontMostSubgoal(msg);
        }

        //adds a subgoal to the front of the subgoal list
        public void AddSubgoal(Goal<entity_type> g)
        {
            //add the new goal to the front of the list
            _subGoalList.AddFirst(g);
        }

        //this method iterates through the subgoals and calls each one's Terminate
        //method before deleting the subgoal and removing it from the subgoal list
        public void RemoveAllSubgoals()
        {
            foreach (Goal<entity_type> s in _subGoalList)
            {
                s.Terminate();
            }

            _subGoalList.Clear();
        }
    }
}